/*
 * cmp.c
 *
 * analog compare driver.
 *
 * Copyright (C) 2022 Microwell, Inc.
 * Subject to the GNU Public License, version 2.
 *
 * Author: guoming<guoming@microwell.net>
 */
#include "cmp.h"
#include "core.h"

#if (CMP_CHANNEL_MODE == 1)

void cmp_init(void)
{
    uint8_t val;
#if ((GPIO_P00_CMP_MODE == CMP0) && (GPIO_P04_CMP_MODE == CMP1))
    val = CMP1P_0V3 | CMP0P_0V9;
#elif (GPIO_P00_CMP_MODE == CMP0)
    val = CMP0P_0V9;
#elif (GPIO_P04_CMP_MODE == CMP1)
    val = CMP1P_0V3;
#endif
    WRITE_REG(CMPCON0, val);

#if ((GPIO_P00_CMP_MODE == CMP0) && (GPIO_P04_CMP_MODE == CMP1))
    val = CMP1DE_3_SCLK | CMP0DE_3_32K;
#elif (GPIO_P00_CMP_MODE == CMP0)
    val = CMP0DE_3_32K;
#elif (GPIO_P04_CMP_MODE == CMP1)
    val = CMP1DE_3_SCLK;
#endif
    /* Set CMP debounce time */
    WRITE_REG(CMPCON1, val);

#if ((GPIO_P00_CMP_MODE == CMP0) && (GPIO_P04_CMP_MODE == CMP1))
    val = CMP0IM_0_1 | CMP1IM_0_1;
#elif (GPIO_P00_CMP_MODE == CMP0)
    val = CMP0IM_0_1;
#elif (GPIO_P04_CMP_MODE == CMP1)
    val = CMP1IM_0_1;
#endif    
    /* Set interrupt mode and clear pending bit */
    WRITE_REG(CMPCON2, val);

#if ((GPIO_P00_CMP_MODE == CMP0) && (GPIO_P04_CMP_MODE == CMP1))
    val = (1 << 0) | (1 << 5);
#elif (GPIO_P00_CMP_MODE == CMP0)
    val = (1 << 0);
#elif (GPIO_P04_CMP_MODE == CMP1)
    val = (1 << 5);
#endif

    cmp_disable();
    CLEAR_BIT(P0DAT, val);
    CLEAR_BIT(P0MOD, val);
}

void cmp_exit(void)
{
    CLEAR_REG(CMPCON0);
}

void cmp_enable(void)
{
#if (GPIO_P00_CMP_MODE == CMP0)
    SET_BIT(MFP0, 0x03);   /* P00 as CMP0 */
    SET_BIT(MFP0, CMP0EN);   /* CMP0 enable */
    sys_delay_ms(1);
    CLEAR_BIT(CMPCON2, CMP0F);  /* clear pending */
    ECMP = 1;
#endif
    
#if (GPIO_P04_CMP_MODE == CMP1)
    SET_BIT(MFP1, 0x03);   /* P04 as CMP1 */
    SET_BIT(MFP0, CMP1EN);   /* CMP1 enable */
    sys_delay_ms(1);
    CLEAR_BIT(CMPCON2, CMP1F);  /* clear pending */
    ECMP = 1;
#endif
}

void cmp_disable(void)
{
#if (GPIO_P00_CMP_MODE == CMP0)
    ECMP = 0;
    CLEAR_BIT(CMPCON2, CMP0F);     /* clear pending */
    CLEAR_BIT(CMPCON0, CMP0EN);   /* CMP0 disable */
    CLEAR_BIT(MFP0, 0x03);
#endif
    
#if (GPIO_P04_CMP_MODE == CMP1)
    ECMP = 0;
    CLEAR_BIT(CMPCON2, CMP1F);     /* clear pending */
    CLEAR_BIT(CMPCON0, CMP1EN);   /* CMP1 disable */
    CLEAR_BIT(MFP1, 0x03);
#endif
}

bool cmp_is_enable(uint8_t cmp)
{
#if (GPIO_P00_CMP_MODE == CMP0)
    if (cmp == CMP0) {
        return READ_BIT(CMPCON0, CMP0EN);
    }
#endif
#if (GPIO_P04_CMP_MODE == CMP1)
    if (cmp == CMP1) {
        return READ_BIT(CMPCON0, CMP1EN);
    }
#endif
    return false;
}

void cmp_pinmux_get(uint8_t cmp)
{
#if (GPIO_P00_CMP_MODE == CMP0)
    if (cmp == CMP0) {
        if (READ_BIT(MFP0, 0x03) != 0x03) {
            cmp_enable();
        }
    }
#endif
#if (GPIO_P04_CMP_MODE == CMP1)
    if (cmp == CMP1) {
        if (READ_BIT(MFP1, 0x03) != 0x03) {
            cmp_enable();
        }
    }
#endif
}

void cmp_pinmux_put(uint8_t cmp, bool en)
{
    cmp_disable();
#if (GPIO_P00_CMP_MODE == CMP0)
    if (cmp == CMP0) {
        if (en) {
            SET_BIT(P0DAT, (1 << 0));
        } else {
            CLEAR_BIT(P0DAT, (1 << 0));
        }
        _P01_IO_OUTPUT();
    } 
 #endif
 #if (GPIO_P04_CMP_MODE == CMP1) 
    if (cmp == CMP1) {
        if (en) {
            SET_BIT(P0DAT, (1 << 5));
        } else {
            CLEAR_BIT(P0DAT, (1 << 5));
        }
        _P04_IO_OUTPUT();
    }
#endif
}

#if (CONFIG_CMP_USING_IRQ == 1)
static bool cmp_irq_flag;

bool cmp_irq_is_set(void)
{
    return cmp_irq_flag;
}

void set_cmp_irq_flag(void)
{
    cmp_irq_flag = true;
}

void clear_cmp_irq_flag(void)
{
    cmp_irq_flag = false;
}

void adc_cmp_ISR(void) interrupt 7
{
#if (GPIO_P00_CMP_MODE == CMP0)
    if (READ_BIT(CMPCON2, CMP0F)) {
        cmp_irq_cb_0();
        CLEAR_BIT(CMPCON2, CMP0F);
    }
#endif
#if (GPIO_P04_CMP_MODE == CMP1)
    if (READ_BIT(CMPCON2, CMP1F)) {
        cmp_irq_cb_1();
        CLEAR_BIT(CMPCON2, CMP1F);
    }
#endif
}
#endif
#endif
